#include<iostream>
#include<pthread.h>
#include<unistd.h>
#include<queue>
using namespace std;
#define NUM 5//创建线程个数

//线程池
template<class T>
class Threadpool
{
  public:
    Threadpool(int num=NUM)
      :_thread_num(num)
    {
      pthread_mutex_init(&_mutex,nullptr);
      pthread_cond_init(&_cond,nullptr);
    }
    ~Threadpool()
    {
      pthread_mutex_destroy(&_mutex);
      pthread_cond_destroy(&_cond);
    }

  private:
    void LockQueue()
    {
      pthread_mutex_lock(&_mutex);
    }
    void UnlockQueue()
    {
      pthread_mutex_unlock(&_mutex);
    }
    bool Isempty()
    {
      return _task_queue.size()==0;
    }
    void wait()
    {
      pthread_cond_wait(&_cond,&_mutex);
    }
    void wakeup()
    {
      pthread_cond_signal(&_cond);
    }

  public:
    static void* Routine(void* arg)
    {
      pthread_detach(pthread_self());
      Threadpool* self = (Threadpool*)arg;
      //线程池里的线程在这里不断地从任务队列获取任务进行处理
      while(1)
      {
        self->LockQueue();
        while(self->Isempty())
        {
          self->wait();
        }
        T task;
        self->Pop(task);
        self->UnlockQueue();
        //处理任务
        printf("thread: %d,消费task: %d\n",pthread_self(), task);
      }
    }
    void ThreadpoolInit()//创建_thread_num个线程
    {
      pthread_t tid;
      for(int i=0;i<_thread_num;i++)
      {
        pthread_create(&tid,nullptr,Routine,this);
      }
    }
//主线程调用往任务队列塞任务
    void Push(const T& task)
    {
      LockQueue();
      _task_queue.push(task);
      UnlockQueue();
      wakeup();//唤醒线程，通知有任务了
    }
//领取任务，线程池的线程调用
    void Pop(T& task)
    {
      task = _task_queue.front();
      _task_queue.pop();
    }

  private:
    queue<T> _task_queue;//任务队列
    int _thread_num;//线程池的线程的数量
    pthread_mutex_t _mutex;//互斥锁
    pthread_cond_t _cond;//条件变量
};
